using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using System.IO;
using System.Collections.Generic;
using System.Net;

namespace PriceBoard
{
    struct Company
    {
        public string code;
        public string name;
    }
	/// <summary>
	/// Summary description for ctlMain.
	/// </summary>
	public class ctlMain : System.Windows.Forms.UserControl
    {
        private ListView lvPriceBoard;
        private ColumnHeader chCode;
        private ColumnHeader chPrice;
        private ColumnHeader chChange;
        private ColumnHeader chChangePercentage;
        private LinkLabel llAll;
        private LinkLabel llFavorite;
        private ListViewColumnSorter lvwColumnSorter;
        private List<string> lstFavoriteCodes;
        private string sListFavoritePath;
        private WebClient webClient;
        private int iMode;
        private ColumnHeader chRefPrice;
        private ColumnHeader chVolume;
        private string currency;
        private int nMarket;
        private string[] MarketNames;
        private string[] PriceBoardServices;
        private Timer timerUpdatePriceBoard;
        private Button btnTimer;
        private ComboBox cbMarkets;
        private WebBrowser webBrowser;
        private IContainer components;
        private Label lbCompanyName;
        private string PriceService;
        private Label lbUp;
        private Label lbUnchanged;
        private Label lbDown;
        private List<Company> lstCompanies;

		public ctlMain()
		{
			// This call is required by the Windows.Forms Form Designer.
			InitializeComponent();

			// TODO: Add any initialization after the InitializeComponent call

		}

		/// <summary> 
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if(components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Component Designer generated code
		/// <summary> 
		/// Required method for Designer support - do not modify 
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
            this.components = new System.ComponentModel.Container();
            this.lvPriceBoard = new System.Windows.Forms.ListView();
            this.chCode = new System.Windows.Forms.ColumnHeader();
            this.chRefPrice = new System.Windows.Forms.ColumnHeader();
            this.chPrice = new System.Windows.Forms.ColumnHeader();
            this.chVolume = new System.Windows.Forms.ColumnHeader();
            this.chChange = new System.Windows.Forms.ColumnHeader();
            this.chChangePercentage = new System.Windows.Forms.ColumnHeader();
            this.llAll = new System.Windows.Forms.LinkLabel();
            this.llFavorite = new System.Windows.Forms.LinkLabel();
            this.timerUpdatePriceBoard = new System.Windows.Forms.Timer(this.components);
            this.btnTimer = new System.Windows.Forms.Button();
            this.cbMarkets = new System.Windows.Forms.ComboBox();
            this.lbCompanyName = new System.Windows.Forms.Label();
            this.lbUp = new System.Windows.Forms.Label();
            this.lbUnchanged = new System.Windows.Forms.Label();
            this.lbDown = new System.Windows.Forms.Label();
            this.SuspendLayout();
            // 
            // lvPriceBoard
            // 
            this.lvPriceBoard.Activation = System.Windows.Forms.ItemActivation.OneClick;
            this.lvPriceBoard.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
                        | System.Windows.Forms.AnchorStyles.Left)));
            this.lvPriceBoard.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
            this.chCode,
            this.chRefPrice,
            this.chPrice,
            this.chVolume,
            this.chChange,
            this.chChangePercentage});
            this.lvPriceBoard.FullRowSelect = true;
            this.lvPriceBoard.GridLines = true;
            this.lvPriceBoard.HoverSelection = true;
            this.lvPriceBoard.Location = new System.Drawing.Point(16, 73);
            this.lvPriceBoard.Name = "lvPriceBoard";
            this.lvPriceBoard.Size = new System.Drawing.Size(375, 356);
            this.lvPriceBoard.TabIndex = 0;
            this.lvPriceBoard.UseCompatibleStateImageBehavior = false;
            this.lvPriceBoard.View = System.Windows.Forms.View.Details;
            this.lvPriceBoard.MouseClick += new System.Windows.Forms.MouseEventHandler(this.lvPriceBoard_MouseClick);
            this.lvPriceBoard.DoubleClick += new System.EventHandler(this.lvPriceBoard_DoubleClick);
            this.lvPriceBoard.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.lvPriceBoard_ColumnClick);
            // 
            // chCode
            // 
            this.chCode.Text = "Code";
            // 
            // chRefPrice
            // 
            this.chRefPrice.Text = "Ref Price";
            // 
            // chPrice
            // 
            this.chPrice.Text = "Price";
            // 
            // chVolume
            // 
            this.chVolume.Text = "Volume";
            // 
            // chChange
            // 
            this.chChange.Text = "Change";
            // 
            // chChangePercentage
            // 
            this.chChangePercentage.Text = "%Change";
            // 
            // llAll
            // 
            this.llAll.ActiveLinkColor = System.Drawing.Color.Blue;
            this.llAll.AutoSize = true;
            this.llAll.Location = new System.Drawing.Point(213, 19);
            this.llAll.Name = "llAll";
            this.llAll.Size = new System.Drawing.Size(18, 13);
            this.llAll.TabIndex = 1;
            this.llAll.TabStop = true;
            this.llAll.Text = "All";
            this.llAll.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.llAll_LinkClicked);
            // 
            // llFavorite
            // 
            this.llFavorite.ActiveLinkColor = System.Drawing.Color.Blue;
            this.llFavorite.AutoSize = true;
            this.llFavorite.Location = new System.Drawing.Point(253, 19);
            this.llFavorite.Name = "llFavorite";
            this.llFavorite.Size = new System.Drawing.Size(45, 13);
            this.llFavorite.TabIndex = 2;
            this.llFavorite.TabStop = true;
            this.llFavorite.Text = "Favorite";
            this.llFavorite.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.llFavorite_LinkClicked);
            // 
            // btnTimer
            // 
            this.btnTimer.Location = new System.Drawing.Point(127, 15);
            this.btnTimer.Name = "btnTimer";
            this.btnTimer.Size = new System.Drawing.Size(67, 21);
            this.btnTimer.TabIndex = 3;
            this.btnTimer.Text = "Timer";
            this.btnTimer.UseVisualStyleBackColor = true;
            this.btnTimer.Click += new System.EventHandler(this.btnTimer_Click);
            // 
            // cbMarkets
            // 
            this.cbMarkets.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
            this.cbMarkets.FormattingEnabled = true;
            this.cbMarkets.Location = new System.Drawing.Point(16, 16);
            this.cbMarkets.Name = "cbMarkets";
            this.cbMarkets.Size = new System.Drawing.Size(92, 21);
            this.cbMarkets.TabIndex = 4;
            this.cbMarkets.SelectedIndexChanged += new System.EventHandler(this.cbMarkets_SelectedIndexChanged);
            // 
            // lbCompanyName
            // 
            this.lbCompanyName.AutoSize = true;
            this.lbCompanyName.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(163)));
            this.lbCompanyName.Location = new System.Drawing.Point(427, 19);
            this.lbCompanyName.Name = "lbCompanyName";
            this.lbCompanyName.Size = new System.Drawing.Size(0, 20);
            this.lbCompanyName.TabIndex = 5;
            // 
            // lbUp
            // 
            this.lbUp.AutoSize = true;
            this.lbUp.ForeColor = System.Drawing.Color.Lime;
            this.lbUp.Location = new System.Drawing.Point(13, 49);
            this.lbUp.Name = "lbUp";
            this.lbUp.Size = new System.Drawing.Size(21, 13);
            this.lbUp.TabIndex = 6;
            this.lbUp.Text = "Up";
            // 
            // lbUnchanged
            // 
            this.lbUnchanged.AutoSize = true;
            this.lbUnchanged.ForeColor = System.Drawing.Color.Yellow;
            this.lbUnchanged.Location = new System.Drawing.Point(73, 49);
            this.lbUnchanged.Name = "lbUnchanged";
            this.lbUnchanged.Size = new System.Drawing.Size(63, 13);
            this.lbUnchanged.TabIndex = 7;
            this.lbUnchanged.Text = "Unchanged";
            // 
            // lbDown
            // 
            this.lbDown.AutoSize = true;
            this.lbDown.ForeColor = System.Drawing.Color.Red;
            this.lbDown.Location = new System.Drawing.Point(135, 49);
            this.lbDown.Name = "lbDown";
            this.lbDown.Size = new System.Drawing.Size(35, 13);
            this.lbDown.TabIndex = 8;
            this.lbDown.Text = "Down";
            // 
            // ctlMain
            // 
            this.BackColor = System.Drawing.Color.Black;
            this.Controls.Add(this.lbDown);
            this.Controls.Add(this.lbUnchanged);
            this.Controls.Add(this.lbUp);
            this.Controls.Add(this.lbCompanyName);
            this.Controls.Add(this.cbMarkets);
            this.Controls.Add(this.btnTimer);
            this.Controls.Add(this.llFavorite);
            this.Controls.Add(this.llAll);
            this.Controls.Add(this.lvPriceBoard);
            this.Name = "ctlMain";
            this.Size = new System.Drawing.Size(1010, 434);
            this.Load += new System.EventHandler(this.ctlMain_Load);
            this.ResumeLayout(false);
            this.PerformLayout();

		}
		#endregion

		private void ctlMain_Load(object sender, System.EventArgs e)
        {
            this.lstCompanies = new List<Company>();
            this.webBrowser = new System.Windows.Forms.WebBrowser();
            // 
            // webBrowser
            // 
            this.webBrowser.Location = new System.Drawing.Point(419, 73);
            this.webBrowser.MinimumSize = new System.Drawing.Size(20, 20);
            this.webBrowser.Name = "webBrowser";
            this.webBrowser.Size = new System.Drawing.Size(450, 356);
            this.webBrowser.TabIndex = 5;
            this.webBrowser.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top;
            this.Controls.Add(this.webBrowser);

            // Initialize list view control
            lvwColumnSorter = new ListViewColumnSorter();
            lvPriceBoard.ListViewItemSorter = lvwColumnSorter;

            // Initialize config
            StreamReader sr = new StreamReader("config.txt");
            while (!sr.EndOfStream)
            {
                switch (sr.ReadLine().Normalize())
                {
                    case "[currency]":
                        currency = sr.ReadLine().Trim();
                        break;
                    case "[nMarkets]":
                        nMarket = int.Parse(sr.ReadLine());
                        PriceBoardServices  = new string[nMarket];
                        MarketNames = new string[nMarket];
                        for (int i = 0; i < nMarket; i++)
                        {
                            MarketNames[i] = sr.ReadLine().Trim();
                            PriceBoardServices[i] = sr.ReadLine().Trim();
                            cbMarkets.Items.Add(MarketNames[i]);
                        }
                        cbMarkets.SelectedIndex = 0;
                        break;
                    case "[favorite]":
                        sListFavoritePath = sr.ReadLine().Trim();
                        break;
                    case "[Tech chart]":
                        PriceService = sr.ReadLine().Trim();
                        break;
                }
            }
            sr.Close();

            // Load list of favorites
            if (!File.Exists(sListFavoritePath))
                File.Create(sListFavoritePath);
            
            lstFavoriteCodes = new List<string>();
            sr = new StreamReader(sListFavoritePath);
            while (!sr.EndOfStream)
            {
                lstFavoriteCodes.Add(sr.ReadLine().Normalize());
                lstFavoriteCodes.Sort();
            }
            sr.Close();

            // Initialize web client
            iMode = 0;
            webClient = new WebClient();
            webClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webClient_DownloadStringCompleted);

            // Initilize Timer
            btnTimer.Text = "Timer on";
            timerUpdatePriceBoard.Enabled = false;
            timerUpdatePriceBoard.Interval = 16000;
            timerUpdatePriceBoard.Tick += new EventHandler(timerUpdatePriceBoard_Tick);
		}

        void timerUpdatePriceBoard_Tick(object sender, EventArgs e)
        {
            webClient.DownloadStringAsync(new Uri(PriceBoardServices[cbMarkets.SelectedIndex]));
        }

        void webClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            string htmlPriceBoard = e.Result;
            int curPos = 0;
            string firstMarker = "px\">";   // lenght = 4;
            string secondMarker = "<";      // lenght = 1;
            int subStringLen = 0;
            string code, refPrice, curPrice, vol, change;
            int count = 0;
            lvPriceBoard.Items.Clear();
            lvwColumnSorter.Order = SortOrder.None;
            lvwColumnSorter.SortColumn = 0;
            int nUp, nUnchanged, nDown;
            nUnchanged = nUp = nDown = 0;

            while (true)
            {
                // code
                curPos = htmlPriceBoard.IndexOf(firstMarker, curPos+4);
                if (curPos == -1)
                    break;
                subStringLen = htmlPriceBoard.IndexOf(secondMarker, curPos) - curPos - 4;
                code = htmlPriceBoard.Substring(curPos + 4, subStringLen);
                if (iMode == 1 && !lstFavoriteCodes.Contains(code))
                {
                    curPos = htmlPriceBoard.IndexOf(firstMarker, curPos + 4);
                    curPos = htmlPriceBoard.IndexOf(firstMarker, curPos + 4);
                    curPos = htmlPriceBoard.IndexOf(firstMarker, curPos + 4);
                    curPos = htmlPriceBoard.IndexOf(firstMarker, curPos + 4);
                    continue;
                }
                lvPriceBoard.Items.Add(code);
                
                // ref price
                curPos = htmlPriceBoard.IndexOf(firstMarker, curPos+4);
                subStringLen = htmlPriceBoard.IndexOf(secondMarker, curPos) - curPos - 4;
                refPrice = convertCurrency(htmlPriceBoard.Substring(curPos + 4, subStringLen));
                if (refPrice == "")
                    refPrice = "10";
                lvPriceBoard.Items[count].SubItems.Add(refPrice);
                // cur price
                curPos = htmlPriceBoard.IndexOf(firstMarker, curPos+4);
                subStringLen = htmlPriceBoard.IndexOf(secondMarker, curPos) - curPos - 4;
                curPrice = convertCurrency(htmlPriceBoard.Substring(curPos + 4, subStringLen));
                if (curPrice == "") 
                    curPrice = refPrice;
                lvPriceBoard.Items[count].SubItems.Add(curPrice);
                // cur volume
                curPos = htmlPriceBoard.IndexOf(firstMarker, curPos+4);
                subStringLen = htmlPriceBoard.IndexOf(secondMarker, curPos) - curPos - 4;
                vol = convertCurrency(htmlPriceBoard.Substring(curPos + 4, subStringLen));
                lvPriceBoard.Items[count].SubItems.Add(vol);
                // change
                curPos = htmlPriceBoard.IndexOf(firstMarker, curPos+4);
                subStringLen = htmlPriceBoard.IndexOf(secondMarker, curPos) - curPos - 4;
                change = convertCurrency(htmlPriceBoard.Substring(curPos + 4, subStringLen));
                lvPriceBoard.Items[count].SubItems.Add(change);
                // % change
                float fRefPrice = float.Parse(refPrice);
                float fChange = float.Parse(change);
                lvPriceBoard.Items[count].SubItems.Add((100*fChange/fRefPrice).ToString());
                if (fChange == 0)
                {
                    nUnchanged++;
                }
                else
                {
                    if (fChange > 0)
                        nUp++;
                    else
                        nDown++;
                }
                count++;
            }
            lbUp.Text = nUp.ToString();
            lbUnchanged.Text = nUnchanged.ToString();
            lbDown.Text = nDown.ToString();
        }

        private void lvPriceBoard_ColumnClick(object sender, ColumnClickEventArgs e)
        {
            // Determine if clicked column is already the column that is being sorted.
            if (e.Column == lvwColumnSorter.SortColumn)
            {
                // Reverse the current sort direction for this column.
                if (lvwColumnSorter.Order == SortOrder.Ascending)
                {
                    lvwColumnSorter.Order = SortOrder.Descending;
                }
                else
                {
                    lvwColumnSorter.Order = SortOrder.Ascending;
                }
            }
            else
            {
                // Set the column number that is to be sorted; default to ascending.
                lvwColumnSorter.SortColumn = e.Column;
                lvwColumnSorter.Order = SortOrder.Ascending;
            }

            // Perform the sort with these new sort options.
            this.lvPriceBoard.Sort();
        }

        private void llAll_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            iMode = 0;
            webClient.DownloadStringAsync(new Uri(PriceBoardServices[cbMarkets.SelectedIndex]));
        }

        private void llFavorite_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            iMode = 1;
            webClient.DownloadStringAsync(new Uri(PriceBoardServices[cbMarkets.SelectedIndex]));
        }

        private string convertCurrency(string c)
        {
            if (currency == "VN")
                return c.Replace(",","").Replace('.', ',');
            return c.Replace(",", "");
        }

        private void lvPriceBoard_DoubleClick(object sender, EventArgs e)
        {
            if (iMode == 0)
            {
                if (lvPriceBoard.SelectedItems.Count == 1)
                    if (!lstFavoriteCodes.Contains(lvPriceBoard.SelectedItems[0].Text))
                        lstFavoriteCodes.Add(lvPriceBoard.SelectedItems[0].Text);
                lstFavoriteCodes.Sort();
                StreamWriter sw = new StreamWriter(sListFavoritePath);
                int i = 0;
                for (i = 0; i < lstFavoriteCodes.Count - 1; i++)
                    sw.WriteLine(lstFavoriteCodes[i]);
                sw.Write(lstFavoriteCodes[i]);
                sw.Close();
                MessageBox.Show("Added to favorite!");
            }
            else
            {
                if (lvPriceBoard.SelectedItems.Count == 1)
                    lstFavoriteCodes.Remove(lvPriceBoard.SelectedItems[0].Text);
                lvPriceBoard.Items.RemoveAt(lvPriceBoard.SelectedItems[0].Index);
                StreamWriter sw = new StreamWriter(sListFavoritePath);
                int i = 0;
                for (i = 0; i < lstFavoriteCodes.Count - 1; i++)
                    sw.WriteLine(lstFavoriteCodes[i]);
                sw.Write(lstFavoriteCodes[i]);
                sw.Close();
                MessageBox.Show("Removed from favorite!");
            }
        }

        private void btnTimer_Click(object sender, EventArgs e)
        {
            if (btnTimer.Text == "Timer on")
            {
                btnTimer.Text = "Timer off";
                timerUpdatePriceBoard.Enabled = true;
            }
            else
            {
                btnTimer.Text = "Timer on";
                timerUpdatePriceBoard.Enabled = false;
            }
        }

        private void cbMarkets_SelectedIndexChanged(object sender, EventArgs e)
        {
            // Load danh sach cong ty
            lstCompanies.Clear();
            StreamReader sr = new StreamReader(cbMarkets.Text + "\\listCompanies.txt");
            while (!sr.EndOfStream)
            {
                Company comp = new Company();
                comp.code = sr.ReadLine().Trim();
                comp.name = sr.ReadLine().Trim();
                lstCompanies.Add(comp);
            }
            sr.Close();
        }

        private int BinSearch(List<Company> lstCompanies, string code)
        {
            /*int l = 0, r = lstCompanies.Count - 1;
            
            while (l <= r)
            {
                int mid = (l + r) / 2;
                int rsl = lstCompanies[mid].code.CompareTo(code);
                if (rsl == 0)
                    return mid;
                if (rsl < 0)
                    l = mid + 1;
                if (rsl > 0)
                    r = mid - 1;
            }
            return -1;*/
            for (int i = 0; i < lstCompanies.Count; i++)
                if (lstCompanies[i].code == code)
                    return i;
            return -1;
        }

        private void lvPriceBoard_MouseClick(object sender, MouseEventArgs e)
        {
            if (lvPriceBoard.SelectedItems.Count > 0)
            {
                string code = lvPriceBoard.SelectedItems[0].Text;
                int idx = BinSearch(lstCompanies, code);
                if (idx >= 0)
                    lbCompanyName.Text = code + " - " + lstCompanies[idx].name;
                else
                    lbCompanyName.Text = code;
                string path;
                // Price
                path = PriceService.Replace("<code>", code).Replace("<style>", "line").Replace("<range>", "3m");
                webBrowser.Navigate(path);
            }
        }
    }
}
